feat(cmd): add side-aware targeting and trends telemetry#35
Merged
omarshahine merged 2 commits intosteipete:mainfrom Apr 18, 2026
Merged
feat(cmd): add side-aware targeting and trends telemetry#35omarshahine merged 2 commits intosteipete:mainfrom
omarshahine merged 2 commits intosteipete:mainfrom
Conversation
Collaborator
|
Thanks. I'll take a look this weekend. |
Collaborator
|
Merged — thanks for the thorough work here, @igormf! The side-aware targeting and A few small follow-ups I'll handle in separate PRs so this can land now:
Appreciate the clean split-out from #30 and the test coverage. |
omarshahine
added a commit
to omarshahine/eightctl
that referenced
this pull request
Apr 18, 2026
Three independent bugs surfaced while testing steipete#35: 1. HouseholdUserTargets relied on `user.currentDevice.side`, which the Eight Sleep API overwrites with the sentinel "away" for every user when the household is in Away mode. `--side left|right` therefore errored with `available sides: away` for any Away-mode household. Resolve side from the `/devices` payload instead: when Away mode blanks the top-level `leftUserId`/`rightUserId`, the real IDs live inside `awaySides` as `{"leftUserId":"…","rightUserId":"…"}`. Also filter the "available sides" error list to drop the Away sentinel. 2. `resolveAPITimezone` fell back to UTC whenever `time.Local.String()` returned "Local". Port the `/etc/localtime` / `/etc/timezone` / `$TZ` IANA resolution from PR steipete#21 (@dtrinh) so `presence`, `sleep day`, `sleep range`, and `metrics` get the real local zone the API expects. 3. Tokencache picked the first backend whose `Open()` succeeded even when every `Set()` then failed with `Keychain Error (-61)` — e.g., macOS sessions without a writable login keychain. `Save`, `Load`, and `Clear` now fall through to a FileBackend-only keyring so the OAuth token survives across invocations instead of re-running the password grant on every command and tripping Eight Sleep's auth rate limiter. Co-Authored-By: Danny Trinh <noreply@users.noreply.github.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
omarshahine
added a commit
that referenced
this pull request
Apr 18, 2026
…ck (#36) * fix: away-mode side resolution, IANA timezone lookup, keychain fallback Three independent bugs surfaced while testing #35: 1. HouseholdUserTargets relied on `user.currentDevice.side`, which the Eight Sleep API overwrites with the sentinel "away" for every user when the household is in Away mode. `--side left|right` therefore errored with `available sides: away` for any Away-mode household. Resolve side from the `/devices` payload instead: when Away mode blanks the top-level `leftUserId`/`rightUserId`, the real IDs live inside `awaySides` as `{"leftUserId":"…","rightUserId":"…"}`. Also filter the "available sides" error list to drop the Away sentinel. 2. `resolveAPITimezone` fell back to UTC whenever `time.Local.String()` returned "Local". Port the `/etc/localtime` / `/etc/timezone` / `$TZ` IANA resolution from PR #21 (@dtrinh) so `presence`, `sleep day`, `sleep range`, and `metrics` get the real local zone the API expects. 3. Tokencache picked the first backend whose `Open()` succeeded even when every `Set()` then failed with `Keychain Error (-61)` — e.g., macOS sessions without a writable login keychain. `Save`, `Load`, and `Clear` now fall through to a FileBackend-only keyring so the OAuth token survives across invocations instead of re-running the password grant on every command and tripping Eight Sleep's auth rate limiter. Co-Authored-By: Danny Trinh <noreply@users.noreply.github.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style: apply gofumpt formatting to test files CI's gofumpt format check caught whitespace drift in the two new test files. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test: isolate test helpers from the default file keyring The fallback path added in the previous commit made `tokencache.Load` reach into `~/.config/eightctl/keyring/` whenever the primary backend returned ErrKeyNotFound. Existing test helpers (`useTempKeyring` in cmd, `withTestKeyring` in tokencache) only overrode `openKeyring`, so tests that exercised the miss path could see the real filesystem and return stale state — this is what caused `TestRequireAuthFieldsFailsWithoutCacheOrCreds` to fail in CI. Both helpers now override `openKeyring` and `openFileKeyring` with the same tmp-backed opener, keeping the fallback entirely in-process. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style: address self-review nits - Move the IANA-discovery doc comment onto `defaultLocalIANA` where the behavior lives; leave a one-liner on the swappable var. - Make `unwritableKeyring.Remove` return the same sentinel as `Set` so the fake behaves consistently if a future test exercises it. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com> Co-authored-by: Danny Trinh <noreply@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This is the follow-up feature PR requested in #30 after #24 landed.
It keeps the auth/runtime fixes that merged through #24 on
mainand layers the user-facing targeting improvements on top of the current codebase.What Changed
left,right,all, or an explicit household userstatusreport discovered household targeting mode, including split sides vssoloon,off, andtempdefault to all discovered targets when no side/user is providedUX Notes
Examples supported by this branch:
eightctl statuseightctl oneightctl off --side righteightctl temp -- -40eightctl temp --side left 20eightctl presence --from 2026-04-01 --to 2026-04-07If the household is split, side names are surfaced. If the device is effectively single-zone, commands report
soloand target the single available zone.Verification
go test ./...golangci-lint run ./...Context
mainafter fix(client): use form-urlencoded for OAuth token endpoint #24, fix: update API calls for current Eight Sleep endpoints #31, docs: align README with removed metrics/schedule subcommands #32, fix(cmd): stop travel subcommands clobbering persistent viper keys #33, and fix(cmd): read --date/--from/--to from cobra flags instead of viper #34